using System;
using System.Collections;
using UnityEngine;
using Yoozoo.UI.YGUI;
using com.yoozoo.gta.Extension.UGUI.ScreenOrientationEx;
using UnityEngine.UI;

namespace com.yoozoo.gta.Extension.UGUI
{
    public class AutoRollText : ScreenOrientationChangeHandler
    {
        public enum RollType
        {
            Pingpong = 0,
            MiddleToLeftOutside = 1,
            RightOutsideToLeftOutside = 2,
            MiddleToLeftInside = 3,
        }
        public RectMask2D mask2D;
        public RollType rollType = RollType.MiddleToLeftOutside;
        public YText m_text;
        [Header("延迟时间")] public float delay = 1f;
        [Header("移动速度")] public float speed = .2f;
        //[Header("边界检测允许差值")]
        private float limitDiff = 5f;
        private float _textWidth;
        private RectTransform _rect;
        //文本左侧到达Mask左边缘坐标
        private float leftMaxPos = 0;
        //文本右侧到达Mask左边缘坐标
        private float leftMinPos = 0;
        //文本左侧到达Mask右边缘
        private float rightMaxPos = 0;
        //文本右侧到达Mask右边缘
        private float rightMinPos = 0;

        private Coroutine rollCoroutine;
        private Coroutine reRollCoroutine;

        private TextGenerator generator;
        private TextGenerationSettings settings;
        private Vector2 originTxtPos;
        
        public override int Order => (int)AdapterExecuteOrder.GridLayout;
        
        private void Awake()
        {
            _rect = this.transform as RectTransform;
            m_text = m_text ? m_text : GetComponentInChildren<YText>(true);
            this.originTxtPos = m_text.rectTransform.anchoredPosition;
           
            if (mask2D == null)
            {
                mask2D = this.transform.GetComponent<RectMask2D>();
            }
                
            if (m_text == null)
            {
                UnityEngine.Debug.LogError($"请保证AutoRollText组件所挂载的GameObject:{gameObject} 的子节点中含有YText组件", gameObject);
                return;
            }
            
            m_text.AddTextChangeCallBack(CalcTextPos);
            ScreenOrientManager.GetInstance().AddOrientationChangeListener(this);
            // CalcTextPos();
        }

        private new void OnDestroy()
        {
            ScreenOrientManager.GetInstance().RemoveOrientationChangeListener(this);
        }
        
        private void OnEnable()
        {
            CalcTextPos();
        }

        private void OnDisable()
        {
            if (rollCoroutine != null)
            {
                StopCoroutine(rollCoroutine);
                rollCoroutine = null;
            }
            if (reRollCoroutine != null)
            {
                StopCoroutine(reRollCoroutine);
                reRollCoroutine = null;
            }

            if (m_text)
            {
                m_text.rectTransform.anchoredPosition = this.originTxtPos;
            }
            
        }

        public override void ScreenOrientationChange(UnityEngine.ScreenOrientation orientation, bool needForceApply = false)
        {
            if (isActiveAndEnabled && _rect && m_text)
            {
                if (reRollCoroutine != null)
                {
                    StopCoroutine(reRollCoroutine);
                    reRollCoroutine = null;
                }
                reRollCoroutine = StartCoroutine(ReRoll());
            }
        }

        [ContextMenu("重新计算")]
        private void CalcTextPos()
        {
#if  UNITY_EDITOR
            if (!Application.isPlaying)
            {
                Awake();
            }
#endif
            if (!isActiveAndEnabled)
            {
                return;
            }
            // 根据字数 调整 view 宽度
            _textWidth = m_text.preferredWidth;
            Vector2 size = m_text.rectTransform.sizeDelta;
            size.x = _textWidth;
            m_text.rectTransform.sizeDelta = size;

            if (rollCoroutine != null)
            {
                StopCoroutine(rollCoroutine);
                rollCoroutine = null;
                m_text.rectTransform.anchoredPosition = this.originTxtPos;
            }
            
            if (_textWidth > _rect.sizeDelta.x) //文字超出大小
            {
                CalculateTextEdgePosition(_textWidth);
                Vector2 pos = m_text.rectTransform.anchoredPosition;
                pos.x = leftMaxPos;
                m_text.rectTransform.anchoredPosition = pos;
                rollCoroutine = StartCoroutine(RollCoroutine());
                this.mask2D.enabled = true;
            }
            else
            {
                mask2D.enabled = false;
                m_text.rectTransform.anchoredPosition = this.originTxtPos;
            }
        }

        void CalculateTextEdgePosition(float textWidth)
        {
            var pivotX = m_text.rectTransform.pivot.x;
            var rectFactor = _rect.pivot.x;
            leftMinPos = -_rect.sizeDelta.x * rectFactor + textWidth * (pivotX - 1);
            leftMaxPos = -_rect.sizeDelta.x * rectFactor + textWidth * pivotX;
            rightMaxPos = _rect.sizeDelta.x * rectFactor + textWidth * pivotX;
            rightMinPos = _rect.sizeDelta.x * rectFactor + textWidth * (pivotX - 1);
        }

        private IEnumerator RollCoroutine()
        {
            Vector2 pos = m_text.rectTransform.anchoredPosition;
            Vector2 current = pos;
            if (delay > 0)
            {
                yield return new WaitForSeconds(delay);
            }

            switch (rollType)
            {
                case RollType.Pingpong:
                {
                    bool leftDir = true;
                    while (true)
                    {
                        if (leftDir)
                        {
                            current.x -= speed;
                        }
                        else
                        {
                            current.x += speed;
                        }

                        m_text.rectTransform.anchoredPosition = current;
                        if (current.x < (leftMinPos - limitDiff))
                        {
                            leftDir = false;
                        }
                        else if (current.x >= pos.x + limitDiff)
                        {
                            leftDir = true;
                        }

                        yield return null;
                    }
                }
                    break;
                case RollType.MiddleToLeftOutside:
                {
                    while (true)
                    {
                        current.x -= speed;
                        m_text.rectTransform.anchoredPosition = current;
                        yield return null;
                        if (current.x < (leftMinPos - limitDiff))
                        {
                            yield return new WaitForSeconds(delay);
                            current.x = pos.x;
                            m_text.rectTransform.anchoredPosition = current;
                            if (delay > 0)
                            {
                                yield return new WaitForSeconds(delay);
                            }
                        }
                    }
                }
                    break;
                case RollType.RightOutsideToLeftOutside:
                {
                    while (true)
                    {
                        current.x -= speed;
                        m_text.rectTransform.anchoredPosition = current;
                        yield return null;
                        if (current.x < (leftMinPos - limitDiff))
                        {
                            yield return new WaitForSeconds(delay);
                            current.x = rightMaxPos;
                            m_text.rectTransform.anchoredPosition = current;
                            if (delay > 0)
                            {
                                yield return new WaitForSeconds(delay);
                            }
                        }
                    }
                }
                    break;
                case RollType.MiddleToLeftInside:
                {
                    while (true)
                    {
                        current.x -= speed;
                        m_text.rectTransform.anchoredPosition = current;
                        yield return null;
                        if (current.x < (rightMinPos - limitDiff))
                        {
                            yield return new WaitForSeconds(delay);
                            current.x = pos.x;
                            m_text.rectTransform.anchoredPosition = current;
                            if (delay > 0)
                            {
                                yield return new WaitForSeconds(delay);
                            }
                        }
                    }
                }
                    break;
                default:
                    break;
            }
        }

        IEnumerator ReRoll()
        {
            if (rollCoroutine != null)
            {
                StopCoroutine(rollCoroutine);
                rollCoroutine = null;
            }
            //当前帧Layout未重新计算完毕，直接计算会计算出错误结果，需等到下一帧再重新计算
            yield return null;
            CalcTextPos();
            reRollCoroutine = null;
        }
    }
}